package service

import (
	"encoding/json"
	"errors"
	"fmt"
	"time"

	"gitee.com/li-zhenyi/yi-nian-zhi-jian/backend/internal/model"
	"gitee.com/li-zhenyi/yi-nian-zhi-jian/backend/internal/repository"
	"gitee.com/li-zhenyi/yi-nian-zhi-jian/backend/pkg/ai"
)

// AdventureService 历练服务接口
// 定义历练系统的所有业务逻辑方法
type AdventureService interface {
	// 开始新的历练
	StartAdventure(userID int64) (*model.AdventureStory, error)
	// 做出选择并获取结果
	MakeChoice(userID int64, adventureID string, choiceID int, conversationID string) (*model.AdventureResult, error)
	// 获取历练历史
	GetAdventureHistory(userID int64, limit int) ([]*model.AdventureRecord, error)
	// 获取历练统计
	GetAdventureStats(userID int64) (*AdventureStats, error)
	// 应用流式历练的奖励（新增）
	ApplyStreamRewards(userID uint, conversationID string, cultivation int, spiritStones int, items []RewardItem) error
}

// AdventureStats 历练统计
type AdventureStats struct {
	TotalAdventures   int64 `json:"total_adventures"`    // 总历练次数
	SuccessCount      int64 `json:"success_count"`       // 成功次数
	TotalCultivation  int64 `json:"total_cultivation"`   // 总获得修为
	TotalSpiritStones int64 `json:"total_spirit_stones"` // 总获得灵石
	TotalItems        int   `json:"total_items"`         // 总获得物品数
}

// RewardItem AI生成的奖励物品结构
// 用于流式历练接口中解析AI返回的物品数据
type RewardItem struct {
	ID     int    `json:"id"`     // AI生成的物品ID（可能不在items表中）
	Name   string `json:"name"`   // 物品名称
	Type   string `json:"type"`   // 物品类型（丹药、符箓、法宝等）
	Effect string `json:"effect"` // 物品效果描述
}

// adventureService 实现AdventureService接口
type adventureService struct {
	userRepo      repository.UserRepository
	adventureRepo repository.AdventureRepository
	itemRepo      repository.ItemRepository
	aiClient      ai.AIClient
	// 存储当前进行中的历练（内存中，实际应用可以用Redis）
	activeAdventures map[int64]*model.AdventureStory
}

// NewAdventureService 创建历练服务实例
func NewAdventureService(
	userRepo repository.UserRepository,
	adventureRepo repository.AdventureRepository,
	itemRepo repository.ItemRepository,
	aiClient ai.AIClient,
) AdventureService {
	return &adventureService{
		userRepo:         userRepo,
		adventureRepo:    adventureRepo,
		itemRepo:         itemRepo,
		aiClient:         aiClient,
		activeAdventures: make(map[int64]*model.AdventureStory),
	}
}

// StartAdventure 开始新的历练
// 参数userID是用户ID
// 返回生成的历练故事和可能的错误
func (s *adventureService) StartAdventure(userID int64) (*model.AdventureStory, error) {
	// 1. 获取用户信息
	user, err := s.userRepo.GetByID(userID)
	if err != nil {
		return nil, err
	}
	if user == nil {
		return nil, errors.New("用户不存在")
	}

	// 2. 构建历练上下文
	ctx, err := s.buildAdventureContext(user)
	if err != nil {
		return nil, err
	}

	// 3. 调用AI生成历练故事
	story, err := s.aiClient.GenerateAdventure(ctx)
	if err != nil {
		return nil, fmt.Errorf("生成历练故事失败: %w", err)
	}
	fmt.Println(story)
	// 4. 保存到活跃历练列表（供后续选择使用）
	s.activeAdventures[userID] = story

	// 5. 返回故事
	return story, nil
}

// MakeChoice 做出选择并获取结果
// 参数userID是用户ID，adventureID是历练ID，choiceID是选择ID
// 返回历练结果和可能的错误
func (s *adventureService) MakeChoice(userID int64, adventureID string, choiceID int, conversationID string) (*model.AdventureResult, error) {
	// 1. 获取用户信息
	user, err := s.userRepo.GetByID(userID)
	if err != nil {
		return nil, err
	}
	if user == nil {
		return nil, errors.New("用户不存在")
	}

	// 2. 获取活跃的历练
	story, exists := s.activeAdventures[userID]
	if !exists || story.AdventureID != adventureID {
		return nil, errors.New("历练不存在或已过期")
	}

	// 3. 验证选择ID
	var selectedChoice *model.AdventureChoice
	for i := range story.Choices {
		if story.Choices[i].ID == choiceID {
			selectedChoice = &story.Choices[i]
			break
		}
	}
	if selectedChoice == nil {
		return nil, errors.New("无效的选择")
	}

	// 4. 调用AI计算结果
		result, err := s.aiClient.CalculateResult(&story.Context, selectedChoice, conversationID)
	if err != nil {
		return nil, fmt.Errorf("计算结果失败: %w", err)
	}

	// 5. 应用奖励到用户
	if err := s.applyRewards(user, result.Reward); err != nil {
		return nil, fmt.Errorf("应用奖励失败: %w", err)
	}

	// 6. 保存历练记录到数据库
	if err := s.saveAdventureRecord(user.ID, story, choiceID, result); err != nil {
		return nil, fmt.Errorf("保存历练记录失败: %w", err)
	}

	// 7. 清除活跃历练
	delete(s.activeAdventures, userID)

	// 8. 返回结果
	return result, nil
}

// GetAdventureHistory 获取历练历史
func (s *adventureService) GetAdventureHistory(userID int64, limit int) ([]*model.AdventureRecord, error) {
	// 验证用户存在
	user, err := s.userRepo.GetByID(userID)
	if err != nil {
		return nil, err
	}
	if user == nil {
		return nil, errors.New("用户不存在")
	}

	// 获取历练记录
	records, err := s.adventureRepo.GetByUserID(userID, limit)
	if err != nil {
		return nil, err
	}

	return records, nil
}

// GetAdventureStats 获取历练统计
func (s *adventureService) GetAdventureStats(userID int64) (*AdventureStats, error) {
	// 验证用户存在
	user, err := s.userRepo.GetByID(userID)
	if err != nil {
		return nil, err
	}
	if user == nil {
		return nil, errors.New("用户不存在")
	}

	// 获取所有历练记录
	records, err := s.adventureRepo.GetByUserID(userID, 0)
	if err != nil {
		return nil, err
	}

	// 统计数据
	stats := &AdventureStats{
		TotalAdventures: int64(len(records)),
	}

	for _, record := range records {
		if record.Success {
			stats.SuccessCount++
		}
		stats.TotalCultivation += record.CultivationGained
		stats.TotalSpiritStones += record.SpiritStoneGained

		// 统计物品数量
		var items []model.AdventureRewardItem
		if err := json.Unmarshal([]byte(record.ItemsGainedData), &items); err == nil {
			for _, item := range items {
				stats.TotalItems += item.Quantity
			}
		}
	}

	return stats, nil
}

// buildAdventureContext 构建历练上下文
func (s *adventureService) buildAdventureContext(user *model.User) (*model.AdventureContext, error) {
	// 获取历练次数
	count, err := s.adventureRepo.CountByUserID(user.ID)
	if err != nil {
		return nil, err
	}

	// 获取上次历练的简要信息
	lastAdventure := ""
	latestRecord, err := s.adventureRepo.GetLatestByUserID(user.ID)
	if err == nil && latestRecord != nil {
		lastAdventure = latestRecord.Title
	}

	// 构建上下文
	ctx := &model.AdventureContext{
		UserID:         user.ID,
		Realm:          user.Realm,
		RealmLevel:     user.RealmLevel,
		Talent:         user.Talent,
		Comprehension:  user.Comprehension,
		Luck:           user.Luck,
		AdventureCount: int(count),
		LastAdventure:  lastAdventure,
	}

	return ctx, nil
}

// applyRewards 应用奖励到用户
func (s *adventureService) applyRewards(user *model.User, reward model.AdventureReward) error {
	// 增加修为
	user.Cultivation += reward.Cultivation

	// 增加灵石
	user.SpiritStone += reward.SpiritStones

	// 添加物品到背包
	// 这里应该调用ItemService的AddItemToInventory方法
	// 为了简化，我们暂时跳过物品添加的实现
	// TODO: 实现物品添加到背包的逻辑
	if len(reward.Items) > 0 {
		// 将来在这里调用ItemService添加物品
	}

	// 更新用户信息
	if err := s.userRepo.Update(user); err != nil {
		return err
	}

	return nil
}

// saveAdventureRecord 保存历练记录
func (s *adventureService) saveAdventureRecord(
	userID int64,
	story *model.AdventureStory,
	choiceID int,
	result *model.AdventureResult,
) error {
	// 将选择和奖励转换为JSON
	choicesJSON, err := json.Marshal(story.Choices)
	if err != nil {
		return err
	}

	rewardJSON, err := json.Marshal(result.Reward)
	if err != nil {
		return err
	}

	itemsJSON, err := json.Marshal(result.Reward.Items)
	if err != nil {
		return err
	}

	// 创建记录
	record := &model.AdventureRecord{
		UserID:            userID,
		AdventureType:     story.Story.Scene,
		Title:             story.Story.Title,
		StoryContent:      story.Story.Content,
		Scene:             story.Story.Scene,
		PlayerChoice:      choiceID,
		ChoicesData:       string(choicesJSON),
		RewardsData:       string(rewardJSON),
		CultivationGained: result.Reward.Cultivation,
		ItemsGainedData:   string(itemsJSON),
		SpiritStoneGained: result.Reward.SpiritStones,
		Success:           result.Success,
		CreatedAt:         time.Now(),
	}

	// 保存到数据库
	if err := s.adventureRepo.Create(record); err != nil {
		return err
	}

	return nil
}

// ApplyStreamRewards 应用流式历练的奖励
// 此方法用于处理 Coze AI 流式接口返回的奖励数据
// 支持 AI 动态生成新物品（方案B）
func (s *adventureService) ApplyStreamRewards(
	userID uint,
	conversationID string,
	cultivation int,
	spiritStones int,
	items []RewardItem,
) error {
	fmt.Printf("[Service] 开始应用流式奖励: user_id=%d, conversation_id=%s\n", userID, conversationID)
	fmt.Printf("[Service] 奖励详情: 修为+%d, 灵石+%d, 物品x%d\n", cultivation, spiritStones, len(items))

	// 获取用户信息
	user, err := s.userRepo.GetByID(int64(userID))
	if err != nil {
		return fmt.Errorf("获取用户信息失败: %w", err)
	}
	if user == nil {
		return errors.New("用户不存在")
	}

	fmt.Printf("[Service] 当前状态: 修为=%d, 灵石=%d\n", user.Cultivation, user.SpiritStone)

	// 1. 更新用户修为
	if cultivation > 0 {
		user.Cultivation += int64(cultivation)
		fmt.Printf("[Service] 修为更新: +%d -> 总计%d\n", cultivation, user.Cultivation)
	}

	// 2. 更新用户灵石
	if spiritStones > 0 {
		user.SpiritStone += int64(spiritStones)
		fmt.Printf("[Service] 灵石更新: +%d -> 总计%d\n", spiritStones, user.SpiritStone)
	}

	// 3. 保存用户数据
	if err := s.userRepo.Update(user); err != nil {
		return fmt.Errorf("更新用户数据失败: %w", err)
	}
	fmt.Printf("[Service] ✅ 用户数据已更新\n")

	// 4. 处理物品奖励（动态创建新物品）
	itemsData := make([]map[string]interface{}, 0, len(items))
	for _, rewardItem := range items {
		fmt.Printf("[Service] 处理物品: %s (AI_ID:%d, 类型:%s)\n", rewardItem.Name, rewardItem.ID, rewardItem.Type)

		// 尝试通过名称查找已存在的物品（避免重复创建同名物品）
		// 注意：这里简化处理，实际可能需要更复杂的去重逻辑
		existingItem, _ := s.itemRepo.GetItem(int64(rewardItem.ID))
		var itemID int64

		if existingItem == nil {
			// 物品不存在，动态创建新物品（方案B）
			fmt.Printf("[Service] 物品不存在，动态创建: %s\n", rewardItem.Name)

			newItem := &model.Item{
				Name:        rewardItem.Name,
				Type:        rewardItem.Type,
				Description: rewardItem.Effect,
				Effect:      rewardItem.Effect,
				MaxStack:    99, // 默认堆叠数量
			}

			// 这里需要添加创建物品的方法，暂时跳过
			// TODO: 需要在 ItemRepository 中添加 CreateItem 方法
			// 临时方案：使用一个固定的占位符ID
			fmt.Printf("[Service] ⚠️  CreateItem方法待实现，使用占位符\n")
			
			// 为了演示，我们假设创建成功
			// 实际上需要调用类似 s.itemRepo.CreateItem(newItem) 的方法
			itemID = int64(rewardItem.ID) // 使用AI返回的ID作为占位
			
			fmt.Printf("[Service] 📝 需要创建物品: ID=%d, Name=%s, Type=%s, Effect=%s\n", 
				itemID, newItem.Name, newItem.Type, newItem.Effect)
		} else {
			// 物品已存在，使用现有ID
			itemID = existingItem.ID
			fmt.Printf("[Service] 使用已存在物品: ID=%d, Name=%s\n", itemID, existingItem.Name)
		}

		// 添加物品到用户背包
		if err := s.itemRepo.AddItem(int64(userID), itemID, 1); err != nil {
			fmt.Printf("[Service] ⚠️  添加物品到背包失败: %v\n", err)
			// 不中断流程，继续处理其他物品
		} else {
			fmt.Printf("[Service] ✅ 物品已添加到背包: user_id=%d, item_id=%d\n", userID, itemID)
		}

		// 收集物品数据用于记录
		itemsData = append(itemsData, map[string]interface{}{
			"id":       itemID,
			"name":     rewardItem.Name,
			"type":     rewardItem.Type,
			"effect":   rewardItem.Effect,
			"quantity": 1,
		})
	}

	// 5. 记录历练历史
	itemsJSON, err := json.Marshal(itemsData)
	if err != nil {
		fmt.Printf("[Service] ⚠️  序列化物品数据失败: %v\n", err)
		itemsJSON = []byte("[]")
	}

	record := &model.AdventureRecord{
		UserID:            int64(userID),
		AdventureType:     "stream_adventure", // 标记为流式历练
		Title:             fmt.Sprintf("AI历练 - %s", conversationID[:8]), // 使用conversationID前8位
		StoryContent:      fmt.Sprintf("完成了一次AI驱动的历练冒险，获得了丰厚的奖励（修为+%d, 灵石+%d）", cultivation, spiritStones),
		Scene:             "AI生成场景",
		PlayerChoice:      0,
		ChoicesData:       "[]",
		RewardsData:       fmt.Sprintf(`{"cultivation":%d,"spirit_stones":%d,"items":%s}`, cultivation, spiritStones, string(itemsJSON)),
		CultivationGained: int64(cultivation),
		ItemsGainedData:   string(itemsJSON),
		SpiritStoneGained: int64(spiritStones),
		Success:           true,
		CreatedAt:         time.Now(),
	}

	if err := s.adventureRepo.Create(record); err != nil {
		fmt.Printf("[Service] ⚠️  保存历练记录失败: %v\n", err)
		// 不返回错误，因为奖励已经应用成功
	} else {
		fmt.Printf("[Service] ✅ 历练记录已保存: record_id=%d\n", record.ID)
	}

	fmt.Printf("[Service] 🎉 流式奖励应用成功！\n")
	fmt.Printf("[Service] 最终状态: 修为=%d, 灵石=%d, 物品数=%d\n", user.Cultivation, user.SpiritStone, len(items))

	return nil
}
